#include "SampleSphere.h"
#include "GLUtils.h"
#include "LogUtils.h"
#include "math.h"
#include <gtc/matrix_transform.hpp>

// 圆锥

SampleSphere::SampleSphere() {
    m_MVPMatLoc = GL_NONE;
    m_AngleX = 0;
    m_AngleY = 0;

    m_ScaleX = 0.5f;
    m_ScaleY = 0.5f;
}

SampleSphere::~SampleSphere() {

}

void SampleSphere::LoadImage(NativeImage *pImage) {
    //null implement
}

void SampleSphere::Init() {

    char vShaderStr[] =
            "#version 300 es                          \n"
            "layout(location = 0) in vec4 vPosition;  \n"
            "layout(location = 1) in vec4 aColor;  \n"
            "out vec4 vColor;  \n"
            "uniform mat4 u_MVPMatrix;\n"
            "void main()                              \n"
            "{                                        \n"
            "   gl_Position = u_MVPMatrix * vPosition;              \n"
            "   float color;              \n"
            "   if(vPosition.z > 0.0){              \n"
            "       color=vPosition.z;              \n"
            "   }else{              \n"
            "       color=-vPosition.z;              \n"
            "   }              \n"
            "   vColor = vec4(color, color, color, 1.0);              \n"
            "}                                        \n";

    char fShaderStr[] =
            "#version 300 es                              \n"
            "precision mediump float;                     \n"
            "in vec4 vColor;                          \n"
            "out vec4 fragColor;                          \n"
            "void main()                                  \n"
            "{                                            \n"
            "   fragColor = vColor;  \n"
            "}                                            \n";

    m_ProgramObj = GLUtils::CreateProgram(vShaderStr, fShaderStr, m_VertexShader, m_FragmentShader);

    m_MVPMatLoc = glGetUniformLocation(m_ProgramObj, "u_MVPMatrix");
    m_VerticesArray = createPositions();
    m_ColorArray = createColors();
//    circularVertices = createCircularPositions();
//    circularColorVertices = createCircularColors();
    UpdateMVPMatrix(m_MVPMatrix, m_AngleX, m_AngleY, (float)m_ratio);
    glEnable(GL_DEPTH_TEST);
}

void SampleSphere::Draw() {
//    GLushort indices[6] = {0, 1, 2, 0, 2, 3};
    LOG_DEBUG("SampleSphere::Draw\n");

    if (m_ProgramObj == 0)
        return;

//    glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);

    // Use the program object
    glUseProgram(m_ProgramObj);

    // Load the vertex data
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, m_VerticesArray);
    glEnableVertexAttribArray(0);

    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, m_ColorArray);
    glEnableVertexAttribArray(1);

    glUniformMatrix4fv(m_MVPMatLoc, 1, GL_FALSE, &m_MVPMatrix[0][0]);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, circularPixCount);
//    glDrawArrays(GL_TRIANGLE_FAN, 0, circularPixCount);
//    glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(GLushort), GL_UNSIGNED_SHORT, indices);

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);

//    // 圆形
//    glUseProgram(m_ProgramObj);
//
//    // Load the vertex data
//    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, circularVertices);
//    glEnableVertexAttribArray(0);
//
//    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, circularColorVertices);
//    glEnableVertexAttribArray(1);
//
//    glUniformMatrix4fv(m_MVPMatLoc, 1, GL_FALSE, &m_MVPMatrix[0][0]);
//    glDrawArrays(GL_TRIANGLE_FAN, 0, circularPixCount);
////    glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(GLushort), GL_UNSIGNED_SHORT, indices);
//
//    glDisableVertexAttribArray(0);
//    glDisableVertexAttribArray(1);
}

void SampleSphere::Destroy() {
    if (m_ProgramObj) {
        glDeleteProgram(m_ProgramObj);
    }
}

void SampleSphere::setParentViewSize(int w, int h) {
    m_ParentViewWidth = w;
    m_ParentViewHeight = h;
    m_ratio = (float)w/h;

    GLfloat x = 0.5 * w / h;
    LOG_DEBUG("SampleSphere::setParentViewSize w:%d h:%d x%f \n", w, h, x);

//    circularVertices[1] = circularVertices[10]  = x;
//    circularVertices[4] = circularVertices[7] = 0-x;
}
void SampleSphere::OnSurfaceCreated() {
    glEnable(GL_DEPTH_TEST);
}
void SampleSphere::OnSurfaceChanged(int width, int height) {
    setParentViewSize(width, height);
}

GLfloat*  SampleSphere::createPositions() {
    int index = 0;

    GLfloat* data = new GLfloat[circularPixCount*3];
    float step = 5.0f;
    float r1,r2;
    float h1,h2;
    float sinV,cosV;
    for(float i=-90;i<90+step;i+=step){
        r1 = (float)cos(i * MATH_PI / 180.0);
        r2 = (float)cos((i + step) * MATH_PI / 180.0);
        h1 = (float)sin(i * MATH_PI / 180.0);
        h2 = (float)sin((i + step) * MATH_PI / 180.0);
        // 固定纬度, 360 度旋转遍历一条纬线
        float step2=2*step;
        for (float j = 0.0f; j <360.0f+step; j +=step2 ) {
            cosV = (float) cos(j * MATH_PI / 180.0);
            sinV = -(float) sin(j * MATH_PI / 180.0);


            data[index++] = r1 * cosV;
            data[index++] = h1;
            data[index++] = r1 * sinV;
            LOG_DEBUG("SampleSphere::i:%f j:%f x:%f y:%f z:%f\n", i, j, r1 * cosV, h1, r1 * sinV);

            data[index++] = r2 * cosV; //
            data[index++] = h2;
            data[index++] = r2 * sinV;
            LOG_DEBUG("SampleSphere::i:%f j:%f x:%f y:%f z:%f\n", i, j, r2 * cosV, h2, r2 * sinV);


            LOG_DEBUG("SampleSphere::111 index:%d \n", index);
//            index++;
//            index++;
        }
    }
    LOG_DEBUG("SampleSphere::111 index:%d \n", index);

//    index = 0;
//    float radius = 1.0f;
//    GLfloat* data = new GLfloat[circularPixCount*3];
//    data[index++] = 0.0f;
//    data[index++] = 0.0f;
//    data[index++] = -6.0f;
//    float angDegSpan=360.0f/(circularPixCount - 2);
//
//    for(float i=0;i<360+angDegSpan;i+=angDegSpan){
//        data[index++] = (float) (radius*sin(i*MATH_PI/180.0f));
//        data[index++] = (float)(radius*cos(i*MATH_PI/180.0f));
//        data[index++] = 0.0f;
//    }
//    LOG_DEBUG("SampleSphere::createPositions index:%d \n", index);

    return data;
}

GLfloat*  SampleSphere::createColors() {
    GLfloat* data = new GLfloat[circularPixCount*4];


//    data[index++] = 0.0f;
//    data[index++] = 0.0f;
//    data[index++] = 0.0f;
//    data[index++] = 1.0f;
    int index = 0;
    for(int i=0;i<circularPixCount; i++){
//        if((int)i%3==0) {
            data[index++] = 1.0f;
            data[index++] = 0.0f;
            data[index++] = 0.0f;
            data[index++] = 1.0f;
//        }else if((int)i%3==1) {
//            data[index++] = 0.0f;
//            data[index++] = 1.0f;
//            data[index++] = 0.0f;
//            data[index++] = 1.0f;
//        }else if((int)i%3==2) {
//            data[index++] = 0.0f;
//            data[index++] = 0.0f;
//            data[index++] = 1.0f;
//            data[index++] = 1.0f;
//        }
    }
//    LOG_DEBUG("SampleSphere::createColors index:%d \n", index);

    return data;
}


GLfloat*  SampleSphere::createCircularPositions() {
    int index = 0;
    float radius = 1.0f;
    GLfloat* data = new GLfloat[circularPixCount*3];
    data[index++] = 0.0f;
    data[index++] = 0.0f;
    data[index++] = 0.0f;
    float angDegSpan=360.0f/(circularPixCount - 2);

    for(float i=0;i<360+angDegSpan;i+=angDegSpan){
        data[index++] = (float) (radius*sin(i*MATH_PI/180.0f));
        data[index++] = (float)(radius*cos(i*MATH_PI/180.0f));
        data[index++] = 0.0f;
    }
    LOG_DEBUG("SampleSphere::createPositions index:%d \n", index);

    return data;
}

GLfloat*  SampleSphere::createCircularColors() {
    GLfloat* data = new GLfloat[circularPixCount*4];
    int index = 0;
    for(float i=0;i<circularPixCount; i++){
        data[index++] = 1.0f;
        data[index++] = 0.0f;
        data[index++] = 0.0f;
        data[index++] = 1.0f;
    }
    LOG_DEBUG("SampleSphere::createColors index:%d \n", index);

    return data;
}

void SampleSphere::UpdateMVPMatrix(glm::mat4 &mvpMatrix, int angleX, int angleY, float ratio)
{
    LOGCATE("CoordSystemSample::UpdateMVPMatrix angleX = %d, angleY = %d, ratio = %f", angleX, angleY, ratio);
    angleX = angleX % 360;
    angleY = angleY % 360;

    //转化为弧度角
    float radiansX = static_cast<float>(MATH_PI / 180.0f * angleX);
    float radiansY = static_cast<float>(MATH_PI / 180.0f * angleY);


    // Projection matrix
    glm::mat4 Projection = glm::ortho(-ratio, ratio, -1.0f, 1.0f, 0.1f, 100.0f);
    //glm::mat4 Projection = glm::frustum(-ratio, ratio, -1.0f, 1.0f, 4.0f, 100.0f);
    //glm::mat4 Projection = glm::perspective(45.0f,ratio, 0.1f,100.f);

    // View matrix
    glm::mat4 View = glm::lookAt(
            glm::vec3(0, 0, 4), // Camera is at (0,0,1), in World Space
            glm::vec3(0, 0, 0), // and looks at the origin
            glm::vec3(0, 1, 0)  // Head is up (set to 0,-1,0 to look upside-down)
    );

    // Model matrix
    glm::mat4 Model = glm::mat4(1.0f);
    Model = glm::scale(Model, glm::vec3(m_ScaleX, m_ScaleY, 1.0f));
    Model = glm::rotate(Model, radiansX, glm::vec3(1.0f, 0.0f, 0.0f));
    Model = glm::rotate(Model, radiansY, glm::vec3(0.0f, 1.0f, 0.0f));
    Model = glm::translate(Model, glm::vec3(0.0f, 0.0f, 0.0f));

    mvpMatrix = Projection * View * Model;

}